/**
 * @author:albert
 * @date:2016年7月2日
 */
package com.bkbw.live.battle.business.items;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bkbw.live.battle.bean.BeanConvertor;
import com.bkbw.live.battle.bean.Pair;
import com.bkbw.live.battle.business.UnitObject;
import com.bkbw.live.battle.business.items.UnitBagItemChange.UnitBagItemOpType;
import com.bkbw.live.battle.database.bean.BagBeanManager;
import com.bkbw.live.battle.database.bean.BagBeanManager.BagEquipmentBaseBean;
import com.bkbw.live.battle.database.bean.BagBeanManager.BagEquipmentBean;
import com.bkbw.live.battle.database.bean.BagBeanManager.BagItemBean;
import com.bkbw.live.battle.database.bean.BagBeanManager.BagWeaponBean;
import com.bkbw.live.battle.database.bean.DBodyEquipmentBean;
import com.bkbw.live.common.GameConfig;
import com.bkbw.live.common.business.ItemTypeUtil;
import com.bkbw.live.common.dataproto.ClientToBattleServerPb.BagEquipment;
import com.bkbw.live.common.dataproto.ClientToBattleServerPb.BagEquipmentBase;
import com.bkbw.live.common.dataproto.ClientToBattleServerPb.BagItem;
import com.bkbw.live.common.dataproto.ClientToBattleServerPb.BS2CBuyItemResp.Builder;
import com.bkbw.live.common.dataproto.CommonMessagePb.DBagItemPb;
import com.bkbw.live.common.dataproto.CommonMessagePb.HashIntInt;
import com.bkbw.live.common.dataproto.CommonMessagePb.HashLongInt;
import com.bkbw.live.common.dataproto.EnumConfigPb.EquipType;
import com.bkbw.live.common.util.Utils;

/**
 * @author albert
 *
 */
public class UnitBag {
	Logger logger = LoggerFactory.getLogger(GameConfig.LoggerName);
	// uid -> bagitem
	private HashMap<Long, UnitBagItem> bagItems = new HashMap<Long, UnitBagItem>();
	
	UnitEquipmentBase[] onBodyEquipment = new UnitEquipmentBase[EquipType.DoubleShield_VALUE];
	
	public List<UnitBagItemChange> putonEquipment(EquipType type, UnitEquipmentBase equipment){
		
		UnitBagItemChange offEquip;
		UnitBagItemChange onEquip;
		switch (type.getNumber()){
		case EquipType.MainHand_VALUE:
		case EquipType.SubHand_VALUE:
			if (!(equipment instanceof UnitWeapon)) {
				return null;
			}
		}
		List<UnitBagItemChange> list = new LinkedList<UnitBagItemChange>();
		// 同一个装备，已经在身上，再次点击装备即取下
		if (onBodyEquipment[type.getNumber() - 1] != null && onBodyEquipment[type.getNumber() - 1].getUid() == equipment.getUid()) {
			if (onBodyEquipment[type.getNumber() - 1].getIsEquip() == 1) {
				onBodyEquipment[type.getNumber() - 1].setIsEquip(0);
				onBodyEquipment[type.getNumber() - 1] = null;
				list.add(new UnitBagItemChange(equipment, UnitBagItemOpType.UpdateEquip));
			}
			else {
				onBodyEquipment[type.getNumber() - 1] = null;
				list.add(new UnitBagItemChange(equipment, UnitBagItemOpType.UpdateEquip));
			}
			return list;
		}
		if (onBodyEquipment[type.getNumber() - 1] != null) {
			onBodyEquipment[type.getNumber() - 1].setIsEquip(0);
			list.add(new UnitBagItemChange(onBodyEquipment[type.getNumber() - 1], UnitBagItemOpType.UpdateEquip));
		}
		onBodyEquipment[type.getNumber() - 1] = equipment;
		equipment.setIsEquip(1);
		list.add(new UnitBagItemChange(onBodyEquipment[type.getNumber() - 1], UnitBagItemOpType.UpdateEquip));
		return list;
	}
	
	public List<UnitBagItemChange> putonEquipment(long uid){
		
		UnitBagItem unitBagItem = getUnitBagItemByUid(uid);
		if (unitBagItem != null && (unitBagItem instanceof UnitEquipmentBase)) {
			UnitEquipmentBase equipmentBase = (UnitEquipmentBase)unitBagItem;
			BagEquipmentBaseBean bagEquipmentBaseBean = BagBeanManager.getInstance().getBagEquipmentBaseBeanById(equipmentBase.getItemId());
			EquipType equipType = EquipType.valueOf(Integer.parseInt(bagEquipmentBaseBean.getEquipType()));
			return putonEquipment(equipType, equipmentBase);
		}
		if (unitBagItem == null) {
			logger.debug("putonEquipment "+uid+" no bag item");
		}
		else if (!(unitBagItem instanceof UnitEquipmentBase)) {
			logger.debug("putonEquipment "+uid+" no not equip");
		}
		return null;
	}
	
	public void loadEquipment(long uid) {
		UnitBagItem unitBagItem = getUnitBagItemByUid(uid);
		if (unitBagItem != null && unitBagItem instanceof UnitEquipmentBase) {
			UnitEquipmentBase equipmentBase = (UnitEquipmentBase)unitBagItem;
			try {
				BagEquipmentBaseBean bagEquipmentBaseBean = BagBeanManager.getInstance().getBagEquipmentBaseBeanById(equipmentBase.getItemId());
				//EquipType equipType = EquipType.valueOf(Integer.parseInt(equipmentBase.getEquipType()));
				EquipType equipType = EquipType.valueOf(Integer.parseInt(bagEquipmentBaseBean.getEquipType()));
				onBodyEquipment[equipType.getNumber() - 1] = equipmentBase;
			}
			catch (Exception e){
				e.printStackTrace();
			}
		}
	}
	
	// 加载玩家背包时，把已安装的装备放置到装备槽上
	public void loadEquipment(EquipType type, long uid) {
		UnitBagItem unitBagItem = getUnitBagItemByUid(uid);
		if (unitBagItem != null && unitBagItem instanceof UnitEquipmentBase) {
			UnitEquipmentBase equipmentBase = (UnitEquipmentBase)unitBagItem;
			
			try {
				BagEquipmentBaseBean bagEquipmentBaseBean = BagBeanManager.getInstance().getBagEquipmentBaseBeanById(equipmentBase.getItemId());
				
				EquipType equipType = EquipType.valueOf(Integer.parseInt(bagEquipmentBaseBean.getEquipType()));
				if (equipType != type) {
					logger.debug("charid "+this.owner.getAgent().getCharId()+" equip incorrect uid "+uid);
					return;
				}
				// 身上有此装备，但装备的isEquip却没有同步
				if (equipmentBase.getIsEquip() == 0) {
					logger.debug("charid "+this.owner.getAgent().getCharId()+" data not sync "+equipmentBase.getUid());
				}
				onBodyEquipment[equipType.getNumber() - 1] = equipmentBase;
				
			}
			catch (Exception e){
				e.printStackTrace();
			}
		}
	}
	
	public List<DBagItemPb> getOnBodyEquipmentToDBagItemPbs() {
		
		List<DBagItemPb> list = new LinkedList<DBagItemPb>();
		
		for(int i = 0; i < onBodyEquipment.length; ++i) {
			if (onBodyEquipment[i] != null) {
				try {
					list.add(BeanConvertor.transUnitBagItem2DBagItemPb(onBodyEquipment[i]));
				}
				catch (Exception e){
					
				}
			}
		}
		
		return list;
	}
	
	public DBodyEquipmentBean getOnBodyEquipmentToDbBodyEquipment() {
		DBodyEquipmentBean bean = new DBodyEquipmentBean();
		bean.setCharId(owner.getAgent().getCharId());
		for (int i = 1; i <= EquipType.DoubleShield_VALUE; ++i){
			
			UnitEquipmentBase unitEquipmentBase = onBodyEquipment[i - 1];
			EquipType type = EquipType.valueOf(i);
			String typeName = type.toString();
			Method getter = null;
			try {
				getter = bean.getClass().getMethod("get"+typeName+"Uid");
				
			}
			catch (Exception e){
				e.printStackTrace();
			}
			Method setter = null;
			try {
				setter = bean.getClass().getMethod("set"+typeName+"Uid", getter.getReturnType());
				if (onBodyEquipment[i - 1] == null) {
					setter.invoke(bean, 0L);
				}
				else {
					setter.invoke(bean, unitEquipmentBase.getUid());
				}
				
			}
			catch (Exception e){
				logger.debug("getOnBodyEquipmentToDbBodyEquipment exception on field " + typeName);
				e.printStackTrace();
			}
		}
		return bean;
	}
	
//	public void getoffEquipment(EquipType type){
//		if (onBodyEquipment[type.getNumber() - 1] != null) {
//			onBodyEquipment[type.getNumber() - 1].setIsEquip(0);
//			onBodyEquipment[type.getNumber() - 1] = null;
//		}
//	}
	
	public UnitEquipmentBase[] getOnBodyEquipment() {
		return onBodyEquipment;
	}
	
	
	private UnitObject owner;
	
	public void setUnitObject(UnitObject owner) {
		this.owner = owner;
	}
	
	public UnitBagItem getUnitBagItemByUid(long uid) {
		return bagItems.get(uid);
	}
	
	public void loadUnitBagItem(UnitBagItem item) {
		bagItems.put(item.getUid(), item);
	}
	
	private void addUnitBagItem(UnitBagItem item) {
		bagItems.put(item.getUid(), item);
	}
	
	public void dropUnitBagItem(long uid, int number) {
		UnitBagItem item = bagItems.get(uid);
		int num = item.getNumber();
		if (num <= number) {
			bagItems.remove(uid);
		}
		else {
			item.setNumber(num - number);
		}
	}
	
	public List<Pair<Long, Integer>> dropUnitBagItem(List<HashLongInt> dropItems) {
		List<Pair<Long, Integer>> ret = new LinkedList<Pair<Long, Integer>>();
		for (HashLongInt hashLongInt : dropItems) {
			Pair<Long, Integer> pair = new Pair<Long, Integer>();
			long uid = hashLongInt.getKey();
			UnitBagItem item = bagItems.get(uid);
			int num = item.getNumber();
			int subnum = hashLongInt.getValue();
			if (num <= subnum) {
				bagItems.remove(uid);
			}
			else {
				item.setNumber(num - subnum);
			}
			
			pair.setKey(uid);
			pair.setValue((num - subnum) >= 0 ? (num - subnum) : 0);
			ret.add(pair);
		}
		return ret;
	}
	
	public List<HashLongInt> dropUnitBagItemRetHashLongInt(List<HashLongInt> dropItems) {
		List<HashLongInt> ret = new LinkedList<HashLongInt>();
		for (HashLongInt hashLongInt : dropItems) {
			HashLongInt.Builder builder = HashLongInt.newBuilder();
			long uid = hashLongInt.getKey();
			UnitBagItem item = bagItems.get(uid);
			int num = item.getNumber();
			int subnum = hashLongInt.getValue();
			if (num <= subnum) {
				bagItems.remove(uid);
			}
			else {
				item.setNumber(num - subnum);
			}
			builder.setKey(uid);
			builder.setValue((num - subnum) >= 0 ? (num - subnum) : 0);
			ret.add(builder.build());
		}
		return ret;
	}
	
	public List<UnitBagItemChange> dropUnitBagItemRetBagItem(List<HashLongInt> dropItems) {
		List<UnitBagItemChange> ret = new LinkedList<UnitBagItemChange>();
		for (HashLongInt hashLongInt : dropItems) {
			
			long uid = hashLongInt.getKey();
			UnitBagItem item = bagItems.get(uid);
			if (item == null) {
				logger.debug("uid "+uid+" is not exist in bag");
				continue;
			}
			if (item instanceof UnitEquipmentBase) {
				UnitEquipmentBase equipmentBase = (UnitEquipmentBase)item;
				if (equipmentBase.getIsEquip() == 1) {
					logger.debug("uid "+uid+" is in equip");
					continue;
				}
			}
			int num = item.getNumber();
			int subnum = hashLongInt.getValue();
			if (num <= subnum) {
				ret.add(new UnitBagItemChange(item, UnitBagItemOpType.Delete));
				bagItems.remove(uid);
			}
			else {
				item.setNumber(num - subnum);
				ret.add(new UnitBagItemChange(item, UnitBagItemOpType.UpdateNumber));
			}
		}
		return ret;
	}
	
	public List<UnitBagItemChange> useUnitBagItemRetBagItem(List<HashLongInt> dropItems) {
		List<UnitBagItemChange> ret = new LinkedList<UnitBagItemChange>();
		for (HashLongInt hashLongInt : dropItems) {
			long uid = hashLongInt.getKey();
			UnitBagItem item = bagItems.get(uid);
			int num = item.getNumber();
			int subnum = hashLongInt.getValue();
			if (num <= subnum) {
				ret.add(new UnitBagItemChange(item, UnitBagItemOpType.Delete));
				bagItems.remove(uid);
			}
			else {
				item.setNumber(num - subnum);
				ret.add(new UnitBagItemChange(item, UnitBagItemOpType.UpdateNumber));
			}
		}
		return ret;
	}
	
//	private void addNewUnitBagItem(HashIntInt additem, List<DBagItemPb> list){
//		DBagItemPb.Builder builder = DBagItemPb.newBuilder();
//		int itemId = additem.getKey();
//		
//		int numberToAdd = additem.getValue();
//		int temp = numberToAdd;
//		BagItemBean bagItemBean = BagBeanManager.getInstance().getBagItemBeanById(itemId);
//		int itemType = bagItemBean.getItemType();
//		int repeat = bagItemBean.getRepeat();
//		
//		boolean find = false;
//		for (UnitBagItem unitBagItem : bagItems.values()) {
//			if (unitBagItem.getItemId() == itemId){
//				// 已有格子没有堆叠满，在这个格子上先堆叠满
//				int remain = repeat - unitBagItem.getNumber();
//				if (remain > 0) {
//					// 在已有格子上加入了所有物品
//					if (remain >= numberToAdd) {
//						unitBagItem.setNumber(unitBagItem.getNumber() + numberToAdd);
//						builder.setCharId(owner.getAgent().getCharId());
//						builder.setItemId(itemId);
//						builder.setUid(unitBagItem.getUid());
//						builder.setNumber(unitBagItem.getNumber()); 
//						list.add(builder.build());
//						return;
//					}
//					// 填充旧格子，需要开辟新格子
//					else {
//						temp -= remain;
//						unitBagItem.setNumber(repeat);
//						builder.setCharId(owner.getAgent().getCharId());
//						builder.setItemId(itemId);
//						builder.setUid(unitBagItem.getUid());
//						builder.setNumber(unitBagItem.getNumber()); 
//						list.add(builder.build());
//					}
//				}
//			}
//		}
//		// 需要新的背包格子
//		while (temp > 0) {
//			long newuid = owner.getAgent().getNewUid();
//			while (getUnitBagItemByUid(newuid) != null) {
//				newuid = owner.getAgent().getNewUid();
//			}
//			if (ItemTypeUtil.isItem(itemType)) {
//				UnitBagItem newBagItem = new UnitBagItem();
//				if (temp <= repeat) {
//					newBagItem.setNumber(temp);
//					
//				}
//				else {
//					newBagItem.setNumber(repeat);
//				}
//				newBagItem.setItemId(itemId);
//				newBagItem.setUid(newuid);
//				addUnitBagItem(newBagItem);
//				builder.setCharId(owner.getAgent().getCharId());
//				builder.setItemId(itemId);
//				builder.setUid(newBagItem.getUid());
//				builder.setNumber(newBagItem.getNumber()); 
//				builder.setIsNew(1);
//				list.add(builder.build());
//				temp -= repeat;
//			}
//			else if (ItemTypeUtil.isEquipment(itemType) && (bagItemBean instanceof BagEquipmentBean)) {
//				BagEquipmentBean equipmentBean = (BagEquipmentBean)bagItemBean;
//				UnitEquipment newEquip = new UnitEquipment();
//				if (temp <= repeat) {
//					newEquip.setNumber(temp);
//				}
//				else {
//					newEquip.setNumber(repeat);
//				}
//				newEquip.setItemId(itemId);
//				newEquip.setUid(newuid);
//				// extra mandatory attribute
//				newEquip.setMaxEndurance(equipmentBean.getEndurance());
//				newEquip.setEndurance(equipmentBean.getEndurance());
//				
//				addUnitBagItem(newEquip);
//				
//				builder.setCharId(owner.getAgent().getCharId());
//				builder.setItemId(itemId);
//				builder.setUid(newEquip.getUid());
//				builder.setNumber(newEquip.getNumber()); 
//				builder.setIsNew(1);
//				
//				// extra mandatory attribute
//				builder.setMaxEndurance(equipmentBean.getEndurance());
//				builder.setEndurance(equipmentBean.getEndurance());
//				
//				list.add(builder.build());
//				temp -= repeat;
//			}
//			else if (ItemTypeUtil.isWeapon(itemType) && (bagItemBean instanceof BagWeaponBean)) {
//				BagWeaponBean weaponBean = (BagWeaponBean)bagItemBean;
//				UnitWeapon newWeapon = new UnitWeapon();
//				if (temp <= repeat) {
//					newWeapon.setNumber(temp);
//				}
//				else {
//					newWeapon.setNumber(repeat);
//				}
//				newWeapon.setItemId(itemId);
//				newWeapon.setUid(newuid);
//				// extra mandatory attribute
//				newWeapon.setMaxEndurance(weaponBean.getEndurance());
//				newWeapon.setEndurance(weaponBean.getEndurance());
//				
//				//Utils.copySuperFieldsFromBean(newWeapon, weaponBean);
//				addUnitBagItem(newWeapon);
//				
//				builder.setCharId(owner.getAgent().getCharId());
//				builder.setItemId(itemId);
//				builder.setUid(newWeapon.getUid());
//				builder.setNumber(newWeapon.getNumber()); 
//				builder.setIsNew(1);
//				// extra mandatory attribute
//				builder.setMaxEndurance(weaponBean.getEndurance());
//				builder.setEndurance(weaponBean.getEndurance());
//				list.add(builder.build());
//				temp -= repeat;
//			}
//			else if (ItemTypeUtil.isCollection(itemType)){
//				UnitBagItem newBagItem = new UnitBagItem();
//				if (temp <= repeat) {
//					newBagItem.setNumber(temp);
//					
//				}
//				else {
//					newBagItem.setNumber(repeat);
//				}
//				newBagItem.setItemId(itemId);
//				newBagItem.setUid(newuid);
//				addUnitBagItem(newBagItem);
//				builder.setCharId(owner.getAgent().getCharId());
//				builder.setItemId(itemId);
//				builder.setUid(newBagItem.getUid());
//				builder.setNumber(newBagItem.getNumber()); 
//				builder.setIsNew(1);
//				list.add(builder.build());
//				temp -= repeat;
//			}
//			else {
//				break;
//			}
//		}
//	}
	
	private void addNewUnitBagItem(HashIntInt additem, List<UnitBagItemChange> list){
		
		int itemId = additem.getKey();
		int numberToAdd = additem.getValue();
		int temp = numberToAdd;
		
		BagItemBean bagItemBean = BagBeanManager.getInstance().getBagItemBeanById(itemId);
		int itemType = bagItemBean.getItemType();
		int repeat = bagItemBean.getRepeat();
		
		boolean find = false;
		for (UnitBagItem unitBagItem : bagItems.values()) {
			if (unitBagItem.getItemId() == itemId){
				// 已有格子没有堆叠满，在这个格子上先堆叠满
				int remain = repeat - unitBagItem.getNumber();
				if (remain > 0) {
					// 在已有格子上加入了所有物品
					if (remain >= numberToAdd) {
						unitBagItem.setNumber(unitBagItem.getNumber() + numberToAdd);
						list.add(new UnitBagItemChange(unitBagItem, UnitBagItemOpType.UpdateNumber));
						return;
					}
					// 填充旧格子，需要开辟新格子
					else {
						temp -= remain;
						unitBagItem.setNumber(repeat);
						list.add(new UnitBagItemChange(unitBagItem, UnitBagItemOpType.UpdateNumber));
					}
				}
			}
		}
		// 需要新的背包格子
		while (temp > 0) {
			long newuid = owner.getAgent().getNewUid();
			while (getUnitBagItemByUid(newuid) != null) {
				newuid = owner.getAgent().getNewUid();
			}
			if (ItemTypeUtil.isItem(itemType)) {
				UnitBagItem newBagItem = new UnitBagItem();
				if (temp <= repeat) {
					newBagItem.setNumber(temp);
					
				}
				else {
					newBagItem.setNumber(repeat);
				}
				newBagItem.setItemId(itemId);
				newBagItem.setUid(newuid);
				newBagItem.setCharId(owner.getAgent().getCharId());
				addUnitBagItem(newBagItem);
				list.add(new UnitBagItemChange(newBagItem, UnitBagItemOpType.Insert));
				temp -= repeat;
			}
			else if (ItemTypeUtil.isEquipment(itemType) && (bagItemBean instanceof BagEquipmentBean)) {
				BagEquipmentBean equipmentBean = (BagEquipmentBean)bagItemBean;
				UnitEquipment newEquip = new UnitEquipment();
				if (temp <= repeat) {
					newEquip.setNumber(temp);
				}
				else {
					newEquip.setNumber(repeat);
				}
				newEquip.setItemId(itemId);
				newEquip.setUid(newuid);
				newEquip.setCharId(owner.getAgent().getCharId());
				// extra mandatory attribute
				newEquip.setMaxEndurance(equipmentBean.getEndurance());
				newEquip.setEndurance(equipmentBean.getEndurance());
				
				addUnitBagItem(newEquip);
				
				list.add(new UnitBagItemChange(newEquip, UnitBagItemOpType.Insert));
				temp -= repeat;
			}
			else if (ItemTypeUtil.isWeapon(itemType) && (bagItemBean instanceof BagWeaponBean)) {
				BagWeaponBean weaponBean = (BagWeaponBean)bagItemBean;
				UnitWeapon newWeapon = new UnitWeapon();
				if (temp <= repeat) {
					newWeapon.setNumber(temp);
				}
				else {
					newWeapon.setNumber(repeat);
				}
				newWeapon.setItemId(itemId);
				newWeapon.setUid(newuid);
				newWeapon.setCharId(owner.getAgent().getCharId());
				// extra mandatory attribute
				newWeapon.setMaxEndurance(weaponBean.getEndurance());
				newWeapon.setEndurance(weaponBean.getEndurance());
				
				//Utils.copySuperFieldsFromBean(newWeapon, weaponBean);
				addUnitBagItem(newWeapon);
				
				list.add(new UnitBagItemChange(newWeapon, UnitBagItemOpType.Insert));
				temp -= repeat;
			}
			else if (ItemTypeUtil.isCollection(itemType)){
				UnitBagItem newBagItem = new UnitBagItem();
				if (temp <= repeat) {
					newBagItem.setNumber(temp);
					
				}
				else {
					newBagItem.setNumber(repeat);
				}
				newBagItem.setItemId(itemId);
				newBagItem.setUid(newuid);
				newBagItem.setCharId(owner.getAgent().getCharId());
				addUnitBagItem(newBagItem);
				list.add(new UnitBagItemChange(newBagItem, UnitBagItemOpType.Insert));
				temp -= repeat;
			}
			else {
				break;
			}
		}
	}
	
//	public List<BagItem> addNewUnitBagItemRetBagItem(List<HashIntInt> addItems) {
//		List<BagItem> ret = new LinkedList<BagItem>();
//		for (HashIntInt hashIntInt : addItems) {
//			addNewUnitBagItem(hashIntInt, ret);
//		}
//		return ret;
//	}
	
//	public List<DBagItemPb> addNewUnitBagItemRetBagItem(HashIntInt addItem) {
//		List<DBagItemPb> ret = new LinkedList<DBagItemPb>();
//		addNewUnitBagItem(addItem, ret);
//		return ret;
//	}
	
	public List<UnitBagItemChange> addNewUnitBagItemRetBagItem(HashIntInt addItem) {
		List<UnitBagItemChange> ret = new LinkedList<UnitBagItemChange>();
		addNewUnitBagItem(addItem, ret);
		return ret;
	}
	
	public List<UnitBagItemChange> addNewUnitBagItem(List<HashIntInt> addItems){
		List<UnitBagItemChange> ret = new LinkedList<UnitBagItemChange>();
		for (HashIntInt hashIntInt : addItems) {
			addNewUnitBagItem(hashIntInt, ret);
		}
		return ret;
	}
}
